package cn.net.isir.controller.miniprogram;

import cn.net.isir.common.*;
import cn.net.isir.core.ShiroUsernamePasswordPhoneToken;
import cn.net.isir.entity.BankCard;
import cn.net.isir.service.BankCardService;
import cn.net.isir.service.UserService;
import cn.net.isir.utils.AppRequestUtils;
import cn.net.isir.utils.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author liuxubo
 * @filename MinipManage.java
 * @package cn.net.isir.controller.miniprogram
 * @email lxb@isir.net.cn
 * @date 2019/03/18
 * @comment
 * @since 1.8
 */
@RestController
@RequestMapping("/minip/manage")
public class MinipLoginController {
    @Resource
    private UserService userService;
    @Resource
    private BankCardService bankCardService;

    /**
     * 登录
     *
     * @param obj 登录用户名密码
     * @return 登录结果
     */
    @RequestMapping(value = "/minpLogin", method = RequestMethod.POST)
    public ResultObject login(RequestObject obj) {
        //声明参数解码后的储存变量
        Map<String, Object> params = new HashMap<>();
        //需要检查的字段名
        List<String> columns = new ArrayList<>();
        columns.add("userName");
        columns.add("password");
        //声明返回值
        ResultObject ro = AppRequestUtils.parametersCheck(obj, params, columns);
        //检查失败则返回缺失的字段提示
        if (ro.getResult() != 200) {
            return ro;
        }
        // 获取小程序传递过来的key
//        String key = String.valueOf(params.get("key"));

        String username = String.valueOf(params.get("userName"));
        String password = String.valueOf(params.get("password"));

        int result = -1;
        try {
            //尝试登陆
            //UsernamePasswordToken upToken = new UsernamePasswordToken(loginUser.getUserName(), loginUser.getPassword());
            ShiroUsernamePasswordPhoneToken phoneToken = new ShiroUsernamePasswordPhoneToken(username, password);
            //如果选择了自动登录,则remember me
            phoneToken.setRememberMe(false);
            //尝试登陆
            SecurityUtils.getSubject().login(phoneToken);
        } catch (UnknownAccountException ex) {
            result = 2;// 未知用户登录
        } catch (IncorrectCredentialsException ex) {
            result = 3;// 用户名密码不匹配
        } catch (LockedAccountException ex) {
            result = 4;// 账户已锁定
        } catch (DisabledAccountException ex) {
            result = 5;// 账户已失效
        } catch (AuthenticationException ex) {
            result = 0;// 其他错误
        }
        //返回信息
        ro.setResult(200);
        ro.setMessage("success");
        Map<String, Object> map = new HashMap<>();
        map.put("loginResult", result == -1 ? 1 : result);
        // 登录失败则返回,不继续做处理
        if (result != -1) {
            ro.setObject(map);
            return ro;
        }
        // 查询银行卡信息
        BankCard bankCard = new BankCard();
        bankCard.setUserId(TokenManager.getTokenId());
        bankCard = bankCardService.selectOne(bankCard);
        map.put("bindingStatus", bankCard == null ? 0 : 1);
        //存入缓存
        String key = StringUtils.randomUUID();
        CacheObjectManager.minipCRMKey.set(key, TokenManager.getTokenId());
        map.put("key", key);
        ro.setObject(map);
        return ro;
    }

    /**
     * 登出
     *
     * @return 请求结果
     */
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public ResultObject logout(RequestObject obj) {
        //声明参数解码后的储存变量
        Map<String, Object> params = new HashMap<>();
        //需要检查的字段名
        List<String> columns = new ArrayList<>();
        columns.add("key");
        //声明返回值
        ResultObject ro = AppRequestUtils.parametersCheck(obj, params, columns);
        //检查失败则返回缺失的字段提示
        if (ro.getResult() != 200) {
            return ro;
        }
        // 获取小程序传递过来的key
        String key = String.valueOf(params.get("key"));
        String userId = CacheObjectManager.minipCRMKey.get(key);
        if (userId == null) {
            return new ResultObject(502, "need login.", null);
        }
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.logout();
        } catch (AuthenticationException ex) {
            ex.printStackTrace();
            return null;
        }
        CacheObjectManager.minipCRMKey.delete(key);
        return new ResultObject(200, "success", null);
    }

    /**
     * 绑定银行卡信息
     *
     * @param obj 参数
     * @return 绑定结果
     */
    @RequestMapping(value = "/bindbankcard", method = RequestMethod.POST)
    public ResultObject bindBankcard(RequestObject obj) {
        //声明参数解码后的储存变量
        Map<String, Object> params = new HashMap<>();
        //需要检查的字段名
        List<String> columns = new ArrayList<>();
        columns.add("key");
        columns.add("name");
        columns.add("bankCardNo");
        columns.add("belongTo");
        columns.add("openingBank");
        //声明返回值
        ResultObject ro = AppRequestUtils.parametersCheck(obj, params, columns);
        //检查失败则返回缺失的字段提示
        if (ro.getResult() != 200) {
            return ro;
        }
        String key = String.valueOf(params.get("key"));
        // 从缓存中,根据key查询获取到的userId
        String userId = CacheObjectManager.minipCRMKey.get(key);
        if (userId == null) {
            return new ResultObject(502, "need login.", null);
        }
        String name = String.valueOf(params.get("name"));
        String bankCardNo = String.valueOf(params.get("bankCardNo"));
        String belongTo = String.valueOf(params.get("belongTo"));
        String openingBank = String.valueOf(params.get("openingBank"));
        BankCard bankCard = new BankCard();
        bankCard.setUserId(userId);
        if (bankCardService.selectCount(bankCard) > 0) {
            return new ResultObject(500, "bank card info has already exist.", null);
        }
        bankCard.setName(name);
        bankCard.setCardNo(bankCardNo);
        bankCard.setBelongTo(belongTo);
        bankCard.setOpeningBank(openingBank);
        int result = bankCardService.insert(bankCard);
        return new ResultObject(200, "success", result);
    }
}
